package com.example.shrio.interceptor;

import com.example.shrio.CurrentUser;
import com.example.shrio.redis.RedisKeys;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.Serializable;
import java.util.concurrent.TimeUnit;

/**
 * web拦截器
 *
 * @author wangkai
 * @date: 2019年6月6日 下午1:47:49
 */
public class AdminInterceptor extends HandlerInterceptorAdapter {

    private static final Logger log = LoggerFactory.getLogger(AdminInterceptor.class);

    @Autowired
    private RedisTemplate<Object, Object> redisTemplate;


    /*
     * (non-Javadoc) 在业务处理器处理请求之前被调用。预处理，可以进行编码、安全控制等处理；
     *
     * @see org.springframework.web.servlet.handler.HandlerInterceptorAdapter#
     * preHandle(javax.servlet.http.HttpServletRequest,
     * javax.servlet.http.HttpServletResponse, java.lang.Object)
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws IOException {
        Subject subject = CurrentUser.getSubject();
        Serializable token = subject.getSession().getId();
        String key = RedisKeys.getShiroSysUserTokenKey(token.toString());
        String account = (String) redisTemplate.opsForValue().get(key);
        if (StringUtils.isNotBlank(account)) {// 已登陆
            String userKey = RedisKeys.getShiroSysUserKey(account);
            String sId = (String) redisTemplate.opsForValue().get(userKey);
            if (sId.equals(token.toString())) {
                Long expire = redisTemplate.getExpire(key);
                // 过期时间小于20分钟的,更新token
                if (expire < 20 * 60) {
                    redisTemplate.expire(key, 30, TimeUnit.MINUTES);
                    redisTemplate.expire(userKey, 30, TimeUnit.MINUTES);
                }
            } else {
                redisTemplate.delete(key);
//                response.sendRedirect("/shrio/logout");
                try {
                    request.getRequestDispatcher("/shrio/logout").forward(request,response);
                } catch (ServletException e) {
                    e.printStackTrace();
                }
                return false;
            }
        } else {
            redisTemplate.delete(key);
//            response.sendRedirect("/shrio/logout");
            try {
                request.getRequestDispatcher("/shrio/logout").forward(request,response);
            } catch (ServletException e) {
                e.printStackTrace();
            }
            return false;
        }
        return true;
    }

    /*
     * (non-Javadoc)
     * 在业务处理器处理请求执行完成后，生成视图之前执行。后处理（调用了Service并返回ModelAndView，但未进行页面渲染），
     * 有机会修改ModelAndView；
     *
     * @see org.springframework.web.servlet.handler.HandlerInterceptorAdapter#
     * postHandle(javax.servlet.http.HttpServletRequest,
     * javax.servlet.http.HttpServletResponse, java.lang.Object,
     * org.springframework.web.servlet.ModelAndView)
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
                           ModelAndView modelAndView) throws Exception {

    }

    /*
     * (non-Javadoc) 在DispatcherServlet完全处理完请求后被调用，可用于清理资源等。返回处理（已经渲染了页面），
     * 可以根据ex是否为null判断是否发生了异常，进行日志记录；
     *
     * @see org.springframework.web.servlet.handler.HandlerInterceptorAdapter#
     * afterCompletion(javax.servlet.http.HttpServletRequest,
     * javax.servlet.http.HttpServletResponse, java.lang.Object,
     * java.lang.Exception)
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {

    }

}
